function FrameBegin()
	--menu speed up 1.0
	n64MemWrite8(0x801DA5CB, 0x02)
	return
end

function BeforeVIFrameEnd()
	local addr_game = 0x801C84A0;	
	local addr_game_info_mode = 0x8011B92C;	
	local gameinfo_mode = n64MemRead32(addr_game_info_mode);
	local func_exec = n64MemRead32(addr_game + 4);
	
	n64ResetParameter("VISync");
	if (gameinfo_mode == 0 --0 normal game
		and func_exec == 0x8009CAC8 --this is gameplay
	) then
		n64SetParameter("VISync", 1);
	end
	return
end

function BeforGTask()
	--NN_LOG("before g Task\n");	
	local addr_game = 0x801C84A0;	
	local addr_game_info_mode = 0x8011B92C;	
	local gameinfo_mode = n64MemRead32(addr_game_info_mode);
	local func_exec = n64MemRead32(addr_game + 4);
    
    --in game play set 20fps FramesPerGTask = 2
    n64ResetParameter("FramesPerGTask");	
	if (gameinfo_mode == 0 --0 normal game
		and func_exec == 0x8009CAC8 --this is gameplay
	) then
        --NN_LOG("normal game\n")
        local framepertask = 1;		
		n64SetParameter("FramesPerGTask", framepertask);
    elseif (gameinfo_mode == 1 --1 is opening play
		and func_exec == 0x8009CAC8 --this is gameplay
	) then
        --NN_LOG("opening play\n")
        local framepertask = 2;		
		n64SetParameter("FramesPerGTask", framepertask);
	elseif (gameinfo_mode == 3 --3 is ending staff
		and func_exec == 0x8009CAC8 --this is gameplay
	) then
		--NN_LOG("this is ending staff\n");			
		local addr_demo_play = 0x801CA254;
		local demoplay_framecnt = n64MemRead16(addr_demo_play + 0x10)
		local addr_demo_data = n64MemRead32(addr_demo_play + 0x4)
		local addr_xx = addr_demo_data + 8;
		while(true) do
			local flag = n64MemRead32(addr_xx);
			--NN_LOG(string.format("flag is 0x%x\n", flag));
			if(flag == 0x000003e8) then
				break;
			elseif(flag == 0x00000001 or flag == 0x00000002) then
				addr_xx = addr_xx + 0xC;
				while(true) do
					local test_value = n64MemRead8(addr_xx);
					addr_xx = addr_xx + 0x10;
					if(test_value == 0xFF) then
						break;
					end
				end
			elseif(flag == 0x0000002D) then
				addr_xx = addr_xx + 0x10;
			elseif(flag >= 0x00000004 and flag <= 0x000003E7) then
				local num = n64MemRead32(addr_xx + 4);
				addr_xx = addr_xx + 0x8 + num *0x30;
			else
				--NN_LOG(string.format("flag is 0x%x\n", flag));
				break;
			end
		end
		addr_xx = addr_xx + 0x8;
		local some_no = n64MemRead16(addr_xx);
		local maxframe = n64MemRead16(addr_xx + 2);
		--NN_LOG(string.format("gameinfomode 0x%x func_exec 0x%x\n", gameinfo_mode, func_exec));
		--NN_LOG(string.format("staff 0x%x 0x%x 0x%x\n", some_no, maxframe, demoplay_framecnt));
		local framepertask = 2;
		if(some_no == 0x37) then
			if(maxframe == 0xC3) then
				n64MemWrite16(addr_xx+2, 0xC3 + 0x6);
			end
		elseif(some_no == 0x38)  then
			if(maxframe == 0xDC) then
				n64MemWrite16(addr_xx+2, 0xDC + 0x7);
			end
		elseif(some_no == 0x39)  then
			if(maxframe == 0xF0) then
				n64MemWrite16(addr_xx+2, 0xF0 + 0x7);
			end
		elseif(some_no == 0x3A)  then
			if(maxframe == 0x118) then
				n64MemWrite16(addr_xx+2, 0x118 + 0x8);
			end
		elseif(some_no == 0x3B)  then
			if(maxframe == 0x118) then
				n64MemWrite16(addr_xx+2, 0x118 + 0x8);
			end
		elseif(some_no == 0x3D)  then
			if(maxframe == 0x140) then
				n64MemWrite16(addr_xx+2, 0x140 + 0x8);
			end
		elseif(some_no == 0x3F)  then
			if(maxframe == 0x104) then
				n64MemWrite16(addr_xx+2, 0x104 + 0x8);
			end
		elseif(some_no == 0x40)  then
			if(maxframe == 0xDC) then
				n64MemWrite16(addr_xx+2, 0xDC + 0x8);
			end
		elseif(some_no == 0x4a)  then
			if(maxframe == 0xFF) then
				n64MemWrite16(addr_xx+2, 0xFF + 0x8);
			end
		elseif(some_no == 0x4b)  then
			if(demoplay_framecnt < 0x18) then
				framepertask = 3;
			else
				framepertask = 4;
			end
			if(maxframe == 0x98) then
				n64MemWrite16(addr_xx+2, 0x98 + 0x9);
			end
		elseif(some_no == 0x4C)  then
			if(demoplay_framecnt < 0xA) then
				framepertask = 5;
			elseif(demoplay_framecnt < 0x1F) then
				framepertask = 4;
			elseif(demoplay_framecnt < 0x7A) then
				framepertask = 3;
			elseif(demoplay_framecnt < 0xE0) then
				local b = bit.band(demoplay_framecnt, 0x1)
				if(b == 0) then
					framepertask = 3;
				else
					framepertask = 2;
				end
			else
				local b = bit.band(demoplay_framecnt, 0x1)
				if(b == 0) then
					framepertask = 3;
				else
					framepertask = 2;
				end
			end			
		elseif(some_no == 0x4E)  then
			local b = math.modf(demoplay_framecnt, 5);
			if(b < 3) then
				framepertask = 3;
			else
				framepertask = 2;
			end
			if(maxframe == 0x9D) then
				n64MemWrite16(addr_xx+2, 0x9D + 0x10);
			end
		elseif(some_no == 0x4D)  then
			if(demoplay_framecnt < 0xB0) then
				framepertask = 2;
			else
				framepertask = 3;
			end
			if(maxframe == 0x127) then
				n64MemWrite16(addr_xx+2, 0x127 + 0x8);
			end
		elseif(some_no == 0x46)  then
			if(maxframe == 0x237) then
				n64MemWrite16(addr_xx+2, 0x237 + 0x10);
			end
		end		
		n64SetParameter("FramesPerGTask", framepertask);
	end
	return
end

function HookFunc_AfterInst(pc, inst)
	--NN_LOG("HookFunc_AfterInst\n")
    if(pc == 0x8009BCB4 and inst == 0x304F0001) then
	   ---000a0142h: 1C 24 31 C2 00 FF 18 40 00 0D 30 4F 00 01   the last instruct is ANDI 0x01.   
		--NN_LOG("m161 m0162 m39 white flashs while attacking----------the last instruct is ANDI 0x01.   -----\n")
		local t2 = n64GPRRead32(2)
		local t15 = bit.band(t2, 0x03)
		n64GPRWrite32(15, t15)
	elseif(pc == 0x8001B4E0 and inst ==0x0C019B0E) then
		--NN_LOG("effect malloc\n")
		--set big memory size to let malloc fail
		n64GPRWrite32(0x04, 0x800000)
	elseif(pc == 0x8001B4E8 and inst ==0x8FA30028) then
		--NN_LOG("after effect malloc\n")
		--set a malloc return value to segment start
		local v1 = n64GPRRead32(0x03)
		local addr = n64MemRead32(v1 + 8)
		n64GPRWrite32(0x2, addr)
	elseif(pc == 0x80025184 and inst ==0x9602001C) then
		--NN_LOG("actor load flags\n")
		--set all actor flag to 2(not free after dead)
		n64GPRWrite32(0x02, 0x2)
	elseif(pc == 0x8009FE34 and inst ==0x8E230000) then
		--will access color buf, sync cpu/gpu
		local v1 = n64GPRRead32(0x03)
		if(v1 > 0) then
			n64WaitGTaskDone()
		end
    end
	
	return
end

function HookFunc_BeforeInst(pc, inst)
    if(pc == 0x800251CC and inst ==0x0C019B0E) then
		--NN_LOG("actor malloc\n")
		--set big memory size to let malloc fail
		n64GPRWrite32(0x07, 0x800000)
	elseif(pc == 0x800251D4 and inst ==0x10000004) then
		--NN_LOG("after actor malloc\n")
		--set a malloc return value to segment start
		local s0 = n64GPRRead32(0x10)
		local addr = n64MemRead32(s0 + 8)
		n64GPRWrite32(0x2, addr)
	end
    return
end